#include <record.h>
#include <sstream>

Record:: Record ()
{
	m_iNumAtts = 0;
	//m_vMyAtts(0);
}
Record::~Record()
{
	/*for(int i=0;i<m_vMyAtts.size();i++)
	{
		m_vMyAtts[i].SetFree();
	}
	m_vMyAtts.clear();
	m_iNumAtts = 0;
	*/
}
// prints the contents of the record to the screen; this requires
// that the schema also be given so that the record can be interpreted
void Record:: SetFree()
{
	for(int i=0;i<m_vMyAtts.size();i++)
	{
		m_vMyAtts[i].FreeMem();
	}
	m_vMyAtts.clear();
	m_iNumAtts = 0;
}
void Record:: Print (Schema &_mySchema)
{
	//_mySchema.PrintName();
	int countNum = _mySchema.GetAttrCount();
	for(int x=0; x<countNum; x++)
	{
		//_mySchema.PrintLn(x);
		m_vMyAtts[x].Print(_mySchema.GetType(x));
		if((2*m_vMyAtts[x].GetBytes()) > _mySchema.GetLength(x))
		{
			printf("\t");
		}
		else
		{
			printf("\t\t");
		}
		printf("|");
	}
	printf("\n");
}

// reads the next record from a pointer to a text file; also requires
// that the schema be given; returns a 0 if there is no data left or
// if there is an error and returns a 1 otherwise

int Record::SuckNextRecord (Schema &mySchema, FILE *textFile)
{	
	int ret = 0;
	if(textFile == NULL)
	{
		return 0;
	}
	if(!feof(textFile))
	{
		ret = 1;
		string line, cut;
		char xy[250];
		fgets (xy , 250 , textFile);
		line = xy;
		int find;
		/*
		if(m_iNumAtts == 0)
		{
		*/
			m_iNumAtts =  mySchema.GetAttrCount();
			//m_aMyAtts  = new Attribute[m_iNumAtts];	
		//}
		m_vMyAtts.clear();
		for(int i=0;i<m_iNumAtts;i++)
		{
			Attribute at;
			find = line.find("|", 0);
			if(find == string::npos)
			{
				return 0;
				//cerr << "Non-matching number of attributes - couldn't find att # " << i+1 << endl;
				//exit(1);
			}
			else
			{
				cut = line.substr(0, find);
				line.erase(0, find);
				/*
				if(mySchema.GetType(i) == Int)
				{
					/*
					int * intVal;
					intVal  = new int;
					*intVal = atoi(cut.c_str());
					*/
					//cout << intVal << " " << endl;
				/*	
					m_aMyAtts[i].SetData(intVal,mySchema.GetType(i));
				}
				else if(mySchema.GetType(i) == Double) //not working to precision???
				{
					/*
					double * doubleVal;
					doubleVal = new double;
					*doubleVal = (double)atof(cut.c_str());
					*/
					//cout << *doubleVal << " "  << cut.c_str() << " " << endl;
				/*	
					m_aMyAtts[i].SetData(doubleVal,mySchema.GetType(i));
				}
				else
				{
					/*
					char* charStringVal = new char[cut.length() + 1];
					memset( charStringVal, '\0', cut.length() + 1 );
					cut.copy( charStringVal, cut.length() + 1);
					*/
				/*	
					m_aMyAtts[i].SetData(charStringVal,mySchema.GetType(i));	
				}
				*/
				at.SetData(cut,mySchema.GetType(i));
				at.Free();
				m_vMyAtts.push_back(at);
				line.erase(0, 1);	//get rid of the pipe delimiter
			}
		}
	}
	else
	{
		ret = 0;
	}
	return ret;
}

// suck the contents of the record fromMe into this; note that after
// this call, fromMe will no longer have anything inside of it
// and fromMe.myAtts should be 0
void Record::Consume (Record &fromMe)
{	
	m_iNumAtts = fromMe.m_iNumAtts;

	m_vMyAtts.clear();
	for(int i=0;i<m_iNumAtts;i++)
	{
		m_vMyAtts.push_back(fromMe.m_vMyAtts[i]);
		fromMe.m_vMyAtts[i].ClearData();
		m_vMyAtts[i].Free();
	}
	fromMe.m_iNumAtts = 0;
}

// make a copy of the record fromMe; note that this is far more
// expensive (requiring a bit-by-bit copy) than Consume, which is
// only a pointer operation
void Record::Copy (Record &copyMe)
{
	int numBytes = copyMe.HowManyBytes();
	char *cPtr = new char[numBytes + 1];

	copyMe.ToBinary(cPtr);
	FromBinary(cPtr);

	delete [] cPtr;
}

// write the record in a "flat" format to the specified memory location;
// returns the length of the record, in bytes
int Record::ToBinary (char *_writeToHere)
{
	char * temp;
	int x = 0;
	int old = sizeof(m_iNumAtts);
	
	//cout<< "m_iNumAtts::"<<m_iNumAtts<<endl;

	memmove(_writeToHere, &m_iNumAtts,sizeof(m_iNumAtts));	

	for(int i=0;i<m_iNumAtts;i++)
	{
		temp = _writeToHere + old;
		x = m_vMyAtts[i].ToBinary(temp);
		old = old + x;
		//cout << "ToAmount: " << old << endl;
	}
	return old;
}

// read the record from the flat, binary format; returns the number of
// bytes that were read
int Record::FromBinary (char *_readFromHere)
{
	char * temp;
	int x = 0;
	int old =  0 ;
	
	memmove(&m_iNumAtts, _readFromHere, sizeof(m_iNumAtts));
	old= sizeof(m_iNumAtts);

	//m_aMyAtts = new Attribute[m_iNumAtts];
	m_vMyAtts.clear();
	for(int i=0;i<m_iNumAtts;i++)
	{
		Attribute at;
		temp = _readFromHere + old;
		x = at.FromBinary(temp);
		at.Free();
		m_vMyAtts.push_back(at);
		old = old + x;
		//cout << "FromAmount: " << old << endl;
	}
	return old;
}

// this returns the number of bytes that would be needed to store the
// record in a flat format
int Record::HowManyBytes ()
{

// Record : |4 byte number of atts | [4bytes for size of a particular Att | Att itself]*


	int x = 0;
	
	for(int i=0;i<m_iNumAtts;i++)
	{
		x = m_vMyAtts[i].GetBytes() + x;
	}
	x = x + (m_iNumAtts + 1) * sizeof(int);
	return x; 
}
void Record::declareAtts(int _sizeSchema)
{
	m_iNumAtts = _sizeSchema;
	//m_aMyAtts  = new Attribute[m_iNumAtts];
}

int Record::Compare(Attribute at,int _place,int _compare,Type _ty)
{
	int ret = m_vMyAtts[_place].Compare(at, _ty, _compare);
	return ret;
}
